package com.jl.sms;

import java.security.GeneralSecurityException;
import com.jl.card.JL;
import com.jl.sms.userdata.UserData;
import com.jl.sms.userdata.UserDataParam;
import com.jl.util.BinUtil;
import com.jl.util.HexUtil;
import com.jl.util.LengthUtil;

public class GSM implements ISMS {

	private String TP_MTI = "00";// bit no 1 0
	private String TP_MMS = "0";// bit no 2
	private String TP_SRI = "0";// bit no 5
	private String TP_RD = "0";// bit no 2
	private String TP_VPF = "00";// bit no 4 3
	private String TP_RP = "0";// bit no 7
	private String TP_UDHI = "1";// bit no 6
	private String TP_SRR = "0";// bit no 5
	private String TP_MR = "00";
	private String address = "10086";
	private String PID = "40";
	private String DCS = "04";
	private String TP_SCTS = "20121221000004";
	private int type = 0;
	private UserDataParam param;

	private UserData userdata;
	private int code;

	// private static GSM gsm = new GSM();
	private static String TPDU;

	public void setMTI(String TP_MTI) {
		this.TP_MTI = TP_MTI;
	}

	public String getMTI() {
		return this.TP_MTI;
	}

	public String getTP_MMS() {
		return TP_MMS;
	}

	public void setTP_MMS(String TP_MMS) {
		this.TP_MMS = TP_MMS;
	}

	public void setTP_MR(String TP_MR) {
		this.TP_MR = TP_MR;
	}

	public String getTP_SRI() {
		return TP_SRI;
	}

	public void setTP_SRI(String TP_SRI) {
		this.TP_SRI = TP_SRI;
	}

	public String getTP_RP() {
		return TP_RP;
	}

	public void setTP_RP(String TP_RP) {
		this.TP_RP = TP_RP;
	}

	public String getTP_SRR() {
		return TP_SRR;
	}

	public void setTP_SRR(String TP_SRR) {
		this.TP_SRR = TP_SRR;
	}

	public String getTP_RD() {
		return TP_RD;
	}

	public void setTP_RD(String TP_RD) {
		this.TP_RD = TP_RD;
	}

	public String getTP_VPF() {
		return TP_VPF;
	}

	public void setTP_VPF(String TP_VPF) {
		this.TP_VPF = TP_VPF;
	}

	@Override
	public void setUserData(UserData userdata) {
		this.userdata = userdata;
	}

	public void setPID(String PID) {
		this.PID = PID;
	}

	@Override
	public void setAddress(String address) {
		this.address = address.trim();

	}

	public void setSCTS(String SCTS) {
		this.TP_SCTS = SCTS;

	}

	public void setTP_UDHI(String TP_UDHI) {
		this.TP_UDHI = TP_UDHI;
	}

	public void setCode(int code0) {
		this.code = code0;

	}

	public int getCode() {

		return code;
	}

	/* 构建短信 */
	@Override
	public String build() throws GeneralSecurityException{
		param = userdata.getParam();
		init();
		if (TP_MTI.equalsIgnoreCase("01"))// 上行短信
			return submit();
		else if (TP_MTI.equalsIgnoreCase("00"))//下行短信
			return deliver();
		else
			return null;
	}

	/* 构建上行短信 */
	private String submit() throws GeneralSecurityException{
		if (!check_0())
			return null;
		String submit = LengthUtil.bx("BX" + " " + userdata.getUserDataAsValue());
		submit = TP_MR
				+ HexUtil.toHexXX(address.replaceAll("\\s", "").length())
				+ "A1" + DAFormat(address) + PID + DCS + submit;
		// 组织TPDU
		// TPDU = TP_RP + TP_UDHI + TP_SRR + TP_VPF + TP_RD + TP_MTI
		String FristByte = TP_RP + TP_UDHI + TP_SRR + TP_VPF + TP_RD + TP_MTI;
		FristByte = BinUtil.toHex(FristByte);
		if (FristByte.length() == 1)
			FristByte = "0" + FristByte;
		// System.out.println(FristByte);
		submit = LengthUtil.xx("8B" + " " + "xx" + " " + FristByte + submit);
		return HexUtil.format(submit);
	}

	/* 构建下行短信 */
	private String deliver() throws GeneralSecurityException{
		if (!check_0())
			return null;
		String deliver = LengthUtil.bx("BX" + " " + userdata.getUserDataAsValue());// deliver
																		// = UDL
																		// + UD
		deliver = PID + DCS + TP_SCTS + deliver;// deliver = PID + DCS + TP_SCTS
												// + UDL + UD
		// System.out.println(TP_OA);
		// deliver = TP_OA + PID + DCS + TP_SCTS + UDL + UD
		deliver = HexUtil.toHexXX(address.replaceAll("\\s", "").length())
				+ "81" + DAFormat(address) + deliver;
		String FristByte = TP_RP + TP_UDHI + TP_SRI + "00" + TP_MMS + TP_MTI;// TPDU
																				// =
																				// //
																				// TP_RP+TP_UDHI+TP_SRI+"00"+TP_MMS+TP_MTI
		FristByte = BinUtil.toHex(FristByte);
		if (FristByte.length() == 1)
			FristByte = "0" + FristByte;
		deliver = LengthUtil.xx("8B" + " " + "xx" + " " + FristByte + deliver);// 完整短信
		return HexUtil.format(deliver);
	}

	/* 解析下行短信 */
	private static boolean parseDeliver(GSM gsm, String sm, String keyc,
			String keyd) throws GeneralSecurityException {
		int code = -1;
		String TP_UDHI_0 = TPDU.substring(1, 2);// 获得TP_UDHI;
		gsm.setTP_UDHI(TP_UDHI_0);
		gsm.setTP_MMS(TPDU.substring(5, 6));
		gsm.setTP_RP(TPDU.substring(0, 1));
		gsm.setTP_SRI(TPDU.substring(2, 3));
		int len_DA = Integer.parseInt(sm.substring(2, 4), 16);
		if (len_DA % 2 != 0)
			len_DA++;
		gsm.setAddress(toBCD(sm.substring(6, len_DA + 6)));
		sm = sm.substring((3 * 2 + len_DA), sm.length());// 截取信息从PID到最�?
		gsm.setPID(sm.substring(0, 2));
		gsm.setSCTS(sm.substring(4, 18));
		String DCS = sm.substring(2, 4);
		code = getCode(DCS);
		gsm.setCode(code);
		if (code == JL.CODE_UNKNOWN)
			return false;
		int UDL = Integer.parseInt(sm.substring(18, 20), 16);
		sm = sm.substring(20, sm.length());
		if (UDL != sm.length() / 2)
			return false;

		UserData userdata = null;

		if (TP_UDHI_0.equalsIgnoreCase("1"))
			if (!sm.substring(0, 6).equalsIgnoreCase("027000"))
				return false;
			else {
				userdata = UserData.parse(sm, code, keyc, keyd, true);
				gsm.setUserData(userdata);
			}
		else if (TP_UDHI_0.equalsIgnoreCase("0")) {
			userdata = UserData.parse(sm, code, keyc, keyd, false);
			gsm.setUserData(userdata);

		} else
			return false;
		return true;

	}

	/* 解析下行上行短信 */
	private static boolean parseSubmit(GSM gsm, String sm, String keyc,
			String keyd) throws GeneralSecurityException {
		int code = JL.CODE_UNKNOWN;
		// 取得UDHI
		String TP_UDHI_0 = TPDU.substring(1, 2);
		System.out.println(TP_UDHI_0);
		gsm.setTP_UDHI(TP_UDHI_0);
		gsm.setTP_RD(TPDU.substring(5, 6));
		gsm.setTP_SRR(TPDU.substring(2, 3));
		gsm.setTP_VPF(TPDU.substring(3, 5));
		gsm.setTP_RP(TPDU.substring(0, 1));
		gsm.setTP_MR(sm.substring(2, 4));
		// 目标地址长度�?
		int len_DA = Integer.parseInt(sm.substring(4, 6), 16);
		if (len_DA % 2 != 0)
			len_DA++;
		// 截取字符串从PID到最�?
		gsm.setAddress(toBCD(sm.substring(8, len_DA + 8)));
		sm = sm.substring((8 + len_DA), sm.length());
		gsm.setPID(sm.substring(0, 2));
		String DCS = sm.substring(2, 4);
		code = getCode(DCS);
		gsm.setCode(code);
		if (code == JL.CODE_UNKNOWN)
			return false;
		int UDL = Integer.parseInt(sm.substring(4, 6), 16);
		sm = sm.substring(6, sm.length());
		if (UDL != sm.length() / 2)
			return false;

		UserData userdata = null;

		if (TP_UDHI_0.equalsIgnoreCase("1"))
			if (!sm.substring(0, 6).equalsIgnoreCase("027000"))
				return false;
			else {
				userdata = UserData.parse(sm, code, keyc, keyd, true);
				gsm.setUserData(userdata);
			}
		else if (TP_UDHI_0.equalsIgnoreCase("0")) {
			userdata = UserData.parse(sm, code, keyc, keyd, false);
			gsm.setUserData(userdata);
		} else
			return false;
		return true;
	}

	@Override
	public String toString() {
		return null;
	}

	public static ISMS parse(String sms, String keyc, String keyd)
			throws GeneralSecurityException {
		GSM gsm = new GSM();
		int temp;
		sms = sms.replaceAll("\\s", "");
		if (sms.length() % 2 != 0)
			return null;
		String TPDU_Tag = sms.substring(0, 2);
		if (!TPDU_Tag.equalsIgnoreCase("8B"))
			return null;
		int len_0;
		if (!sms.substring(2, 4).equalsIgnoreCase("81")) {
			len_0 = Integer.parseInt(sms.substring(2, 4), 16);
			temp = 0;
		} else {
			len_0 = Integer.parseInt(sms.substring(4, 6), 16);
			temp = 2;
		}
		// 截取字符串从TPDU到最�?
		sms = sms.substring(4 + temp, sms.length());
		if (len_0 != sms.length() / 2)
			return null;
		// 判断TPDU
		TPDU = HexUtil.toBianryString(sms.substring(0, 2));
		// 下行短信
		// 设置MTI
		gsm.setMTI(TPDU.substring(6, 8));
		if (TPDU.substring(6, 8).equalsIgnoreCase("00")) {
			if (!parseDeliver(gsm, sms, keyc, keyd))
				return null;
		} else if (TPDU.substring(6, 8).equalsIgnoreCase("01")) {// 上行短信
			if (!parseSubmit(gsm, sms, keyc, keyd))
				return null;
		} else {
			return null;
		}
		return gsm;
	}

	private String DAFormat(String add) {
		add = add.replaceAll("\\s", "");
		if (add.length() % 2 != 0)
			add = add + "F";
		byte[] adds = HexUtil.parseHexToByteArray(add);
		for (int i = 0; i < adds.length; i++) {
			adds[i] = (byte) ((adds[i] & 0xff) >> 4 | (adds[i] & 0xff) << 4);
		}
		return HexUtil.toHexString(adds);
	}

	private static String toBCD(String add) {
		add = add.replaceAll("\\s", "");
		byte[] adds = HexUtil.parseHexToByteArray(add);
		for (int i = 0; i < adds.length; i++) {
			adds[i] = (byte) ((adds[i] & 0xff) >> 4 | (adds[i] & 0xff) << 4);
		}
		return HexUtil.toHexCompact(adds).replaceAll("F", "");

	}

	private boolean check_0() {
		if (param == null) {
			TP_UDHI = "0";
		} else {
			TP_UDHI = "1";
		}
		if (PID.equalsIgnoreCase("7F")) {
			DCS = "F6";
		} else {
			if ((code = userdata.getCode()) == JL.CODE_ASCII) {
				DCS = "04";
			} else if (code == JL.CODE_BIT7) {
				DCS = "00";
			} else if (code == JL.CODE_UCS2) {
				DCS = "08";
			} else if (code == JL.CODE_HEX) {
				DCS = "04";
			} else
				return false;
		}
		return true;
	}

	private static int getCode(String DCS) {
		String DCS_0 = DCS.substring(0, 1);
		String DCS_1 = DCS.substring(1, 2);
		int code = -1;
		if (DCS_0.equalsIgnoreCase("0")) {
			if (DCS_1.equalsIgnoreCase("0"))
				code = JL.CODE_BIT7;
			else if (DCS_1.equalsIgnoreCase("4"))
				code = JL.CODE_ASCII;
			else if (DCS_1.equalsIgnoreCase("8"))
				code = JL.CODE_UCS2;
			else
				return JL.CODE_UNKNOWN;
		} else if (DCS_0.equalsIgnoreCase("F")) {
			if (DCS_1.equalsIgnoreCase("2"))
				code = JL.CODE_HEX;
			else if (DCS_1.equalsIgnoreCase("6"))
				code = JL.CODE_HEX;
			else
				return JL.CODE_UNKNOWN;
		}
		return code;
	}

	public void init() {
		if ((type & JL.SMS_MT_SUMMIT) != 0){
			TP_MTI = "01";
		}

		if ((type & JL.SMS_DT_SIMDATA) != 0) {
			PID = "7F";
			DCS = "F6";
		}

		if ((type & JL.SMS_SM_HEADER) != 0) {
			TP_UDHI = "1";
		}

	}

	@Override
	public String getAddress() {
		return this.address;
	}

	@Override
	public void setType(int type) {
		this.type = type;
	}

	@Override
	public int getType() {
		return type;
	}

	@Override
	public UserData getUserData() {
		return this.userdata;
	}

}
